<?php

/**
 * Description of Offer
 *
 * @author Kam
 */
class Application_Model_DAO_Payment extends My_DAO_Abstract {

    const DB_PAYMENT = 'Payment';
    const STATUS_NEW = 'new';
    const STATUS_PENDING = 'pending';
    const STATUS_ACCEPTED = 'accepted';
    const STATUS_REJECTED = 'rejected';
    const STATUS_EXPIRED = 'expired';

    public static function getTranslatetPaymentStatus($key = null, $default = '') {
        $data = self::getTranslatetPaymentStatuses();
        if (isset($data[$key])) {
            return $data[$key];
        }
        return $default;
    }

    public static function getTranslatetPaymentStatuses() {
        $t = self::getTranslator();
        return array(
            self::STATUS_ACCEPTED => $t->translate('XXX_PAYMENT_STATUS_ACCEPTED'),
            self::STATUS_NEW => $t->translate('XXX_PAYMENT_STATUS_NEW'),
            self::STATUS_PENDING => $t->translate('XXX_PAYMENT_STATUS_PENDING'),
            self::STATUS_EXPIRED => $t->translate('XXX_PAYMENT_STATUS_EXPIRED'),
            self::STATUS_REJECTED => $t->translate('XXX_PAYMENT_STATUS_REJECTED'),
        );
    }

    public function getStats($startDate, $endDate) {
        $startDate = $startDate . ' 00:00:00';
        $endDate = $endDate . ' 23:59:59';
        $rows = array();
        foreach (self::getTranslatetPaymentStatuses() as $key => $value) {
            $rows[$key] = array();
        }
        $select = $this->getDbTable()->select(Zend_Db_Table::SELECT_WITHOUT_FROM_PART);
        $select->from(array('p' => 'payment'))
                ->where('p.creation_date >= ?', $startDate)
                ->where('p.creation_date <= ?', $endDate);
        $qr = $select->query()->fetchAll();
        $sourceNames = array();
        foreach ($qr as $r) {
            $status = $r['status'];
            $sourceName = $r['source_name'];
            if(!isset($rows[$status][$sourceName])) {
                $rows[$status][$sourceName] = array('items' => array(), 'cnt' => 0, 'amount' => 0.0);
            }
            $rows[$status][$sourceName]['cnt']++;
            $rows[$status][$sourceName]['amount'] += $r['amount'];
//            $rows[$status][$sourceName]['items'][] = $r;
            if(!in_array($sourceName, $sourceNames)) {
                $sourceNames[] = $sourceName;
            }
        }
        $result = array(
            'rows' => $rows,
            'sum' => array(),
            'source_names' => $sourceNames,
        );
        foreach ($rows as $status => $v) {
            $cnt = 0;
            $amount = 0.0;
            foreach ($v as $sourceName => $val) {
                $cnt += $val['cnt'];
                $amount += $val['amount'];
            }
            $result['sum'][$status] = array('cnt' => $cnt, 'amount' => $amount);
        }
        return $result;
    }

    /**
     * @return Zend_Db_Table_Select
     */
    public function getAll() {
        $select = $this->getDbTable()->select(Zend_Db_Table::SELECT_WITHOUT_FROM_PART);
        $select->from(array('p' => 'payment'))
                ->joinLeft(array('u' => 'user'), 'p.created_by=u.user_id', array('email'))
                ->joinLeft(array('xc' => 'catalog'), 'p.source_name="catalog" AND p.source_id=xc.catalog_id', array('catalog_id', 'catalog_code' => 'code', 'catalog_title' => 'title'))
                ->joinLeft(array('xo' => 'offer'), 'p.source_name="offer" AND p.source_id=xo.offer_id', array('offer_id', 'offer_code' => 'code', 'offer_title' => 'title'))
                ->order(array('p.creation_date DESC'));
        return $select;
    }

    public function addNew($data) {
        $record = array();
        $this->setSafety($record, $data, 'amount');
        $this->setSafety($record, $data, 'source_name');
        $this->setSafety($record, $data, 'source_id');
        $this->setSafety($record, $data, 'status');
        $this->setSafety($record, $data, 'comment');

        if (empty($record['status'])) {
            $record['status'] = self::STATUS_NEW;
        }

        $recordId = $this->getDbTable()->insert($record);
        $record = $this->get($recordId);
        return $record;
    }

    public function checkPayments($limit = 5) {
        $payments = $this->getDbTable()->select(Zend_Db_Table::SELECT_WITHOUT_FROM_PART)
                        ->from(array('p' => 'payment'))
                        ->joinLeft(array('b' => 'bank'), 'p.payment_id=b.payment_id', array('bank_status' => 'status'))
                        ->where('p.status IN (?)', array(self::STATUS_PENDING, self::STATUS_NEW))
                        ->where('b.id IS NOT NULL')
                        ->order('p.payment_id DESC')
                        ->query()->fetchAll();
        foreach ($payments as $p) {
            $this->setPaymentStatus($p['payment_id'], $p['bank_status']);
        }
    }

    /**
     * 
     * @param int $paymentId
     * @param string|const $status
     * @param string $comment
     * @param boolean $forceStatus czy logika czy zmianie statusu ma się wykonać tylko wtedy, gdy następuje zmiana statusu (false), czy ma zostać wymuszona (true)
     * @throws My_Exception
     */
    public function setPaymentStatus($paymentId, $status, $comment = null, $forceStatus = false) {
        $row = $this->get($paymentId);
        if (empty($row)) {
            throw new My_Exception('Payment info not exists');
        }
        $method = 'process_' . $row['source_name'];
        $r = $this->$method($row, $status, $forceStatus);
        return $this->setPaymentStatusRaw($paymentId, $status, $comment);
    }

    protected function process_catalog($payment, $newStatus, $forceStatus = false) {
        $sourceId = $payment['source_id'];
        $oldStatus = $payment['status'];
        if (($newStatus == self::STATUS_ACCEPTED) && ($forceStatus || $oldStatus != $newStatus)) {
            $dao = new Application_Model_DAO_Catalog();
            $dao->update($sourceId, array(
                'active' => 1,
            ));
            return true;
        } elseif ($forceStatus || $oldStatus != $newStatus) {
            $dao = new Application_Model_DAO_Catalog();
            $dao->update($sourceId, array(
                'active' => 0,
            ));
            return true;
        }
    }

    protected function process_offer($payment, $newStatus, $forceStatus = false) {
        $sourceId = $payment['source_id'];
        $oldStatus = $payment['status'];
        if (($newStatus == self::STATUS_ACCEPTED) && ($forceStatus || $oldStatus != $newStatus)) {
            $props = My_Utils::getOfferProperties();
            $type = Application_Model_DAO_Offer::TYPE_PAID;
            $activeFrom = date(My_Db_Table::DATE_TIME_PATTERN);
            $activeLength = $props[$type][My_Utils::PROP_OFFER_ACTIVE_DAYS];
            $activeTo = date(My_Db_Table::DATE_PATTERN, time() + ($activeLength + 1) * 24 * 60 * 60) . ' 00:00:00';   // do północy następnego dnia
            $dao = new Application_Model_DAO_Offer();
            $dao->update($sourceId, array(
                'active' => 1,
                'active_length' => $activeLength,
                'active_from' => $activeFrom,
                'active_to' => $activeTo,
            ));
            return true;
        } elseif ($forceStatus || $oldStatus != $newStatus) {
            $dao = new Application_Model_DAO_Offer();
            $dao->update($sourceId, array(
                'active' => 0,
            ));
            return true;
        }
    }

    public function setPaymentStatusRaw($paymentId, $status, $comment = null) {
        $data = array('status' => $status);
        if ($comment != null) {
            $data['comment'] = $comment;
        }
        return $this->getDbTable()->update($data, $paymentId);
    }

    public function getAllTranslatedStatuses() {
        return array(
            self::STATUS_ACCEPTED => $this->translate('XXX_PAYMENT_STATUS_ACCEPTED'),
            self::STATUS_EXPIRED => $this->translate('XXX_PAYMENT_STATUS_EXPIRED'),
            self::STATUS_NEW => $this->translate('XXX_PAYMENT_STATUS_NEW'),
            self::STATUS_PENDING => $this->translate('XXX_PAYMENT_STATUS_PENDING'),
            self::STATUS_REJECTED => $this->translate('XXX_PAYMENT_STATUS_REJECTED'),
        );
    }

    protected function getDbTableNameMap() {
        return array(
            self::DB_PAYMENT => 'Application_Model_DbTable_Payment',
        );
    }

    protected function getDefaultDbTableName() {
        return self::DB_PAYMENT;
    }

}
